/*******************************************************************************
 * Copyright (c) 2011 squid.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     squid - initial API and implementation
 ******************************************************************************/
package com.google.code.cubeirc.editor;


import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import lombok.Getter;
import lombok.Setter;
import lombok.Synchronized;

import org.apache.log4j.Level;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.MovementEvent;
import org.eclipse.swt.custom.MovementListener;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.wb.swt.SWTResourceManager;
import org.pircbotx.Colors;

import com.google.code.cubeirc.base.Base;
import com.google.code.cubeirc.common.ApplicationInfo;
import com.google.code.cubeirc.config.Configuration;
import com.google.code.cubeirc.config.EditorSettings;
import com.google.code.cubeirc.debug.DebuggerQueue;
import com.google.code.cubeirc.ui.EditorPreferences;
import com.google.code.cubeirc.ui.MainForm;

public class EditorManager extends Base {

	@Getter @Setter
	private StyledText editor;
	@Getter @Setter
	private String name;
	@Getter 
	private Customs customs;
	
	@Getter @Setter
	private ArrayList<EditorPopMenuData> popupitems = new ArrayList<EditorPopMenuData>();
	
	@Setter @Getter
	private Menu popupmenu;


	public EditorManager(String name, StyledText editor) {
		super(name);

		setEditor(editor);
		setName(name);

		initEditor();
		


	}
	/**
	 * Init editor fonts/colors
	 */

	private void loadEditorPreferences()
	{
		EditorSettings st;

		if (Configuration.getEditorSettings(getName()) != null)
			st = Configuration.getEditorSettings(getName());
		else
			st = Configuration.getEditorSettings(ApplicationInfo.EDT_DEFAULT_NAME);

		getEditor().setBackground(st.getColorBackground());
		getEditor().setForeground(st.getColorForeground());
		getEditor().setFont(new Font(Display.getCurrent(), st.getFontname(),st.getFontsize(),SWT.NONE));

	}

	private void initEditor()
	{

		loadEditorPreferences();
		getEditor().setEditable(false);	
		getEditor().setLeftMargin(5);

		getEditor().addMouseListener( new MouseAdapter() {
			@Override
			public void mouseDown(MouseEvent arg0) {

				if (arg0.button == 3)
				{
					setPopupmenu(new Menu(getEditor()));
					MenuItem mi = new MenuItem(getPopupmenu(), SWT.POP_UP);
					mi.setText("Edit preferences");
					mi.setImage(SWTResourceManager.getImage(MainForm.class, "/com/google/code/cubeirc/resources/img_colors.png"));
					mi.addSelectionListener(new SelectionAdapter() {
						@Override
						public void widgetSelected(SelectionEvent arg0) {
							EditorPreferences ep = new EditorPreferences(new Shell(), SWT.NONE, getName());
							ep.open();		
							loadEditorPreferences();
						}

					});	
					getPopupmenu().setLocation(Display.getCurrent().getCursorLocation());
					getPopupmenu().setVisible(true);
					
					if (getPopupitems().size() > 0)
					{					

						@SuppressWarnings("unused")
						MenuItem sep = new MenuItem(getPopupmenu(), SWT.SEPARATOR);
						
						for (Iterator<EditorPopMenuData> it = getPopupitems().iterator(); it.hasNext();)
						{
							EditorPopMenuData menuit = it.next();
							MenuItem itm = new MenuItem(getPopupmenu(), SWT.POP_UP);
							itm.setText(menuit.getText());
							itm.setImage(SWTResourceManager.getImage(MainForm.class, menuit.getImage()));
							itm.addSelectionListener(menuit.getAdapter());
						}
						
					}
				}
				super.mouseDown(arg0);
			}
		});

		getEditor().addWordMovementListener(new MovementListener() {

			@Override
			public void getPreviousOffset(MovementEvent arg0) {
				// TODO Auto-generated method stub

			}

			@Override
			public void getNextOffset(MovementEvent arg0) {
				String[] message = arg0.lineText.split(" ");
				int offset = arg0.offset - arg0.lineOffset;
				for (String s : message) {
					if (arg0.lineText.indexOf(s) > offset || arg0.lineText.indexOf(s)+s.length() < offset)
						continue;
					if(s.contains("://")) {
						Program.launch(s);						
					};							
				}
			}								
		});
	}

	public void addToEditorWithoutFormat(final String value)
	{
		asyncExec(new Runnable() {
			
			@Override
			public void run() {
				getEditor().append(value);
				getEditor().setCaretOffset(getEditor().getText().length());
			}
		});

	}
	
	public void addPopupItem(String text, String image, SelectionAdapter adapter)
	{
		getPopupitems().add(new EditorPopMenuData(text, image, adapter));
	}
	private void addToEditor(final String value)
	{
		ParseColoredString(value, getEditor());
	}

	public void setEditable(Boolean value)
	{
		getEditor().setEditable(value);
	}
	public void saveTofile(String filename)
	{
		try
		{
			File outputFile = new File(filename);
			FileOutputStream out = new FileOutputStream(outputFile);
			out.write(getEditor().getText().getBytes());
			out.close();
		}
		catch (Exception ex)
		{

		}
	}

	@Synchronized
	public void addText(String colorsetting, String value, Object ... args)
	{
		addText(colorsetting, String.format(value, args));
	}
	@Synchronized
	public void addText(String colorsetting, String value)
	{
		try
		{
			addText(Configuration.getColorSetting(colorsetting)+value);
		}
		catch(Exception ex)
		{
			ex.printStackTrace();
		}
	}
	@Synchronized
	public void addText(String value, Object ... args)
	{
		addText(String.format(value, args));

	}
	@Synchronized
	public void addText(final String value)
	{
		asyncExec(new Runnable() {

			@Override
			public void run() {
				addToEditor(value);				
			}
		});


	}		
	
	public static void ParseColoredString(final String value, StyledText editor)
	{
		try {
			if (editor.getLineCount() >= ApplicationInfo.EDT_DEFAULT_MAX_LINES)
				editor.setText("");

			String v_value = TemplateManager.replace(value) + " ";
			if (!v_value.endsWith("\n"))
				v_value = v_value + "\n";
			int scrollPos = editor.getTopPixel();
			int ySize = editor.getBounds().height;
			boolean scrollDown = false;
			if (editor.getVerticalBar() != null)
			scrollDown = (scrollPos > (editor.getVerticalBar().getMaximum() - ySize));

			String v_clean = Colors.removeFormattingAndColors(v_value);

			editor.append(v_clean);

			List<StyleRange> styleRanges = ControlCodeParser.parseControlCodes(v_value, editor.getText().length() - v_clean.length());
			for(StyleRange styleRange : styleRanges.toArray(new StyleRange[styleRanges.size()]))
			{
				editor.setStyleRange(styleRange);
			}

			if(scrollDown)editor.setSelection(editor.getText().length()); // scroll the output down

			for (String s : v_clean.split(" ")) {
				if (s.contains("://")) {
					// TODO: make this conform to the global list, and make the
					// global list work
					Color blue = new Color(editor.getDisplay(), 0, 0, 255);
					StyleRange styleRange = new StyleRange();
					styleRange.start = editor.getCharCount()
							- v_clean.length() + v_clean.indexOf(s);
					styleRange.length = s.length();
					styleRange.foreground = blue;
					styleRange.data = s;
					styleRange.underline = true;
					styleRange.underlineStyle = SWT.UNDERLINE_LINK;
					editor.setStyleRange(styleRange);
				}
				if (s.startsWith("<")) {
					Color green = new Color(editor.getDisplay(), 0, 255, 0);
					StyleRange styleRange = new StyleRange();
					styleRange.start = editor.getCharCount() - v_clean.length() + v_clean.indexOf(s)  + 1;								
					styleRange.length = s.length();
					styleRange.data = s;
					styleRange.foreground = green;
					styleRange.underline = true;								
					styleRange.underlineStyle = SWT.UNDERLINE_LINK;
					editor.setStyleRange(styleRange);
				}
			}			
		}	
		catch (Exception ex)
		{
			DebuggerQueue.addDebug("EDITOR", Level.WARN, "Error from %s during adding text %s", "Editor", ex.getMessage());
		}
	}



	public void Clear()
	{
		getEditor().setText("");
	}
}
